package com.warningrc.hibernate;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;

/**
 * hibernate工具类
 * @author <a href="http://weibo.com/weibowarning">王宁</a><br/>
 * email: <a href="mailto:childe.wangning@gmail.com">childe.wangning@gmail.com</a>
 * @date  2012-3-13
 */
public class Utils {
	private static final String HQL = " FROM {0} ";
	private static final String WHERE = " WHERE ";
	private static final String AND = " AND ";

	private Utils() {
	}

	/**
	 * 根据VO的值生成HQL，如果属性值为空，将不生成查询条件
	 * 
	 * @param vo
	 *            值对象 
	 * @param poClass
	 *            持久化类对象  
	 * @param ignoreProperties 
	 *            忽略的属性
	 * @return HQL语句  
	 * @throws Exception
	 */
	public static String getSelectHQL(Object vo, Class<?> poClass,
			final List<String> ignoreProperties) throws Exception {
		Class<?> cls = vo.getClass();
		String hql = MessageFormat.format(HQL, poClass.getSimpleName());
		boolean isWhere = false;
		PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(
				poClass).getPropertyDescriptors();
		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
			String propertyName = propertyDescriptor.getName();
			// 如果在排除列表中，退出循环
			if (ignoreProperties != null
					&& ignoreProperties.contains(propertyName))
				continue;
			Method readMethod = propertyDescriptor.getReadMethod();
			// 如果没有可读可写方法，退出循环
			if (!(readMethod != null && propertyDescriptor.getWriteMethod() != null))
				continue;
			// readMethod.setAccessible(true);
			// 获取Vo对象中对应属性的值
			Method voReadMethod = cls.getMethod(readMethod.getName());
			Object value = voReadMethod.invoke(vo);
			// 如果属性值为空，跳出循环
			if (value == null
					|| (value instanceof String && value.toString().trim()
							.length() == 0))
				continue;
			// 如果没有添加过where关键字，则添加where关键，否则添加and关键字
			if (!isWhere) {
				hql += WHERE;
				isWhere = true;
			} else
				hql += AND;
			// 添加条件
			hql += " " + propertyName + "=" + value + " ";
		}
		return hql;
	}

	/**
	 * @see KQUtils#getSelectHQL(Object, Class, List)
	 */
	public static String getSelectHQL(Object vo, Class<?> poClass,
			String... ignoreClassProperties) throws Exception {
		List<String> ignoreProperties = Arrays.asList(ignoreClassProperties);
		return getSelectHQL(vo, poClass, ignoreProperties);
	}
}
